home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / Interim Executive Decision / SelectorFunction.c < prev    next >
C/C++ Source or Header  |  1998-06-21  |  3KB  |  214 lines

  1. #include <A4Stuff.h>
  2. #include <Errors.h>
  3. #include <Gestalt.h>
  4. #include <TextUtils.h>
  5.  
  6. // Constants
  7.  
  8. #define kAllocChunk 20
  9.  
  10. // Public Routines
  11.  
  12. pascal void* main(int iRoutineSelector);
  13.  
  14. pascal
  15. OSErr
  16. MySelectorFunction
  17. (
  18.     OSType selector,
  19.     long* response
  20. );
  21.  
  22. pascal OSErr FindSelector(OSType selector, long* value);
  23. pascal OSErr RegisterSelector(OSType selector, long value);
  24.  
  25. // The main entry point
  26.  
  27. pascal
  28. void*                                                // The routine pointer
  29. main
  30. (
  31.     int                    iRoutineSelector            // The routine name
  32. )
  33. {
  34.     long                oldA4 = SetCurrentA4 ();
  35.     void*                retval;
  36.  
  37.     if (iRoutineSelector == 1)
  38.     {
  39.         retval = (void*)RegisterSelector;
  40.     }
  41.     else
  42.     {
  43.         retval = (void*)FindSelector;
  44.     }
  45.  
  46.     SetA4 (oldA4);
  47.  
  48.     return (retval);
  49. }
  50.  
  51. // Globals
  52.  
  53. static Handle    gSelectors = nil;
  54. static Handle    gValues = nil;
  55. static long        gAllocSize = 0;
  56. static long        gPatchCount = 0;
  57.  
  58. // Local routines.
  59.  
  60. static long FindPatch(OSType selector);
  61. static OSErr SetGestaltRoutine(OSType selector);
  62.  
  63. //    Find a patched selector.
  64.  
  65. long FindPatch(OSType selector)
  66. {
  67.     long    oldA4 = SetCurrentA4 ();
  68.     long    i;
  69.  
  70.     for (i = 0; (i < gPatchCount) && gSelectors; i++)
  71.     {
  72.         if (selector == ((long*)(*gSelectors))[i])
  73.         {
  74.             SetA4 (oldA4);
  75.             return i;
  76.         }
  77.     }
  78.  
  79.     SetA4 (oldA4);
  80.  
  81.     return -1;
  82. }
  83.  
  84. // The selector function
  85.  
  86. pascal
  87. OSErr
  88. MySelectorFunction
  89. (
  90.     OSType selector,
  91.     long* response
  92. )
  93. {
  94.     long        oldA4 = SetCurrentA4 ();
  95.     long        patchIndex = -1;
  96.     OSErr        err = noErr;
  97.  
  98.     patchIndex = FindPatch(selector);
  99.  
  100.     if (patchIndex < 0)
  101.     {
  102.         err = Gestalt(selector, response);
  103.     }
  104.     else
  105.     {
  106.         *response = ((long*)(*gValues))[patchIndex];
  107.     }
  108.  
  109.     SetA4 (oldA4);
  110.  
  111.     return err;
  112. }
  113.  
  114. // Public entry to find a selector
  115.  
  116. pascal OSErr FindSelector(OSType selector, long* value)
  117. {
  118.     long            oldA4 = SetCurrentA4 ();
  119.  
  120.     OSErr            err = noErr;
  121.     long            response = 0;
  122.     long            patchIndex = -1;
  123.  
  124.     patchIndex = FindPatch(selector);
  125.  
  126.     if (patchIndex >= 0)
  127.     {
  128.         response = ((long*)(*gValues))[patchIndex];
  129.         *value = response;
  130.     }
  131.     else
  132.     {
  133.             err = Gestalt(selector, value);
  134.     }
  135.  
  136.     SetA4 (oldA4);
  137.  
  138.     return err;
  139. }
  140.  
  141. // Make an entry in the tables
  142.  
  143. OSErr SetGestaltRoutine(OSType selector)
  144. {
  145.     long                oldA4 = SetCurrentA4 ();
  146.     OSErr                err = noErr;
  147.     SelectorFunctionUPP    oldFcn;
  148.  
  149.     err = ReplaceGestalt(selector, MySelectorFunction, &oldFcn);
  150.  
  151.     if (err == gestaltUndefSelectorErr)
  152.     {
  153.         err = NewGestalt(selector, MySelectorFunction);
  154.  
  155.         if (err == noErr)
  156.         {
  157.             err = ReplaceGestalt(selector, MySelectorFunction, &oldFcn);
  158.         }
  159.     }
  160.  
  161.     SetA4 (oldA4);
  162.  
  163.     return err;
  164. }
  165.  
  166. // Register a selector
  167.  
  168. pascal OSErr RegisterSelector(OSType selector, long value)
  169. {
  170.     long            oldA4 = SetCurrentA4 ();
  171.     OSErr            err = noErr;
  172.     long            patchIndex = -1;
  173.  
  174.     patchIndex = FindPatch(selector);
  175.  
  176.     if (patchIndex < 0)
  177.     {
  178.         if ((gAllocSize % kAllocChunk) == 0)
  179.         {
  180.             gAllocSize += kAllocChunk;
  181.  
  182.             if (gSelectors)
  183.             {
  184.                 SetHandleSize(gSelectors, gAllocSize);
  185.             }
  186.             else
  187.             {
  188.                 gSelectors = NewHandle(gAllocSize * sizeof(long));
  189.             }
  190.  
  191.             if (gValues)
  192.             {
  193.                 SetHandleSize(gValues, gAllocSize * sizeof(long));
  194.             }
  195.             else
  196.             {
  197.                 gValues = NewHandle(gAllocSize);
  198.             }
  199.  
  200.             patchIndex = gPatchCount;
  201.             gPatchCount++;
  202.         }
  203.     }
  204.  
  205.     (((long*)(*gSelectors))[patchIndex]) = selector;
  206.     (((long*)(*gValues))[patchIndex]) = value;
  207.  
  208.     SetGestaltRoutine(selector);
  209.  
  210.     SetA4 (oldA4);
  211.  
  212.     return (err);
  213. }
  214.